home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Graphics Plus
/
Graphics Plus.iso
/
msdos
/
raytrace
/
dbwrend
/
source
/
cal.c
next >
Wrap
C/C++ Source or Header
|
1989-04-16
|
8KB
|
245 lines
/************************************************************************
* *
* Copyright (c) 1987, David B. Wecker *
* All Rights Reserved *
* *
* This file is part of DBW_Render *
* *
* DBW_Render is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY. No author or distributor accepts *
* responsibility to anyone for the consequences of using it or for *
* whether it serves any particular purpose or works at all, unless *
* he says so in writing. Refer to the DBW_Render General Public *
* License for full details. *
* *
* Everyone is granted permission to copy, modify and redistribute *
* DBW_Render, but only under the conditions described in the *
* DBW_Render General Public License. A copy of this license is *
* supposed to have been given to you along with DBW_Render so you *
* can know your rights and responsibilities. It should be in a file *
* named COPYING. Among other things, the copyright notice and this *
* notice must be preserved on all copies. *
************************************************************************
* *
* Authors: *
* DBW - David B. Wecker *
* *
* Versions: *
* V1.0 870125 DBW - First released version *
* *
************************************************************************/
#define MODULE_CALC
#include "ray.h"
void spherenormal(center,p,n)
vector center,p,n;
{
DIRECTION(center,p,n);
}
void planenormal(ve,vp,n)
vector ve, vp, n;
{
cross(vp,ve,n);
normalize(n);
}
void calcripple(point,w,ripple)
vector point;
int w;
vector ripple;
{
float riprad,temp1,temp2,temp3,damper;
int iriprad;
direction(point,wave[w].center,ripple); /* unit vector pointing away from wave center */
temp1 = wave[w].center[0] - point[0];
temp2 = wave[w].center[1] - point[1];
temp3 = wave[w].center[2] - point[2];
temp1 = temp1 * temp1; /* square it */
temp2 = temp2 * temp2; /* square it */
temp3 = temp3 * temp3; /* square it */
riprad = (float)sqrt(temp1 + temp2 + temp3); /* distance from center to point */
riprad += wave[w].propagate * wave[w].wavelength; /* move it */
riprad /= wave[w].wavelength; /* scale half-wave crest to 0..1 */
if (wave[w].drag == 1.0)
damper = 1.0;
else
damper = (float)pow(wave[w].drag,riprad); /* exponential damping */
iriprad = (int) riprad;
if (iriprad & 1)
{ /* negate it */
ripple[0] = -ripple[0];
ripple[1] = -ripple[1];
ripple[2] = -ripple[2];
}
riprad -= (float) iriprad; /* just get fraction 0..1 */
riprad -= 0.5; /* scale to -0.5 .. +0.5 */
if (riprad < 0.0)
riprad = -riprad; /* absolute value */
riprad = 0.5 - riprad; /* invert */
riprad *= damper;
riprad *= wave[w].amplitude;
vecscale(riprad,ripple,ripple); /* scale bend */
}
void noise3(point,total)
vector point,
total;
{
vector ripple;
float s;
int w;
veczero(total);
for (w = 0; w < numwaves; w++)
{
calcripple(point,w,ripple); /* calculate the wave perturbation */
vecsum(ripple,total,total); /* sum the ripple bends */
}
s = NORM(total);
if (s < 0.001)
total[0] = 1.0;
else
{
s = 1.0 / s;
vecscale(s,total,total); /* Make it unit vector */
}
}
float noise(point)
vector point;
{
vector total;
float s;
noise3(point,total);
s = total[0] + total[1] + total[2]; /* sum is between -sqrt(3)..+sqrt(3) */
s += sqrt3; /* now between 0.0 and 2*sqrt(3) */
s /= sqrt3times2; /* scale to range 0..1 */
return( s );
}
float turbulence(point)
vector point;
{
vector temp;
float t,scale;
if (numwaves > 0)
{
t = 0.0;
scale = 1.0;
while (scale < 64.0)
{
vecscale(scale,point,temp);
t += fabs(noise(temp) / scale);
scale *= 2.0;
}
}
else
{
t = 1.5;
}
return( t );
}
void dodirection(val,eye2,d2,atten,amblits)
vector val;
vector eye2;
vector d2;
float atten;
int amblits;
{
vector transparency,nextval,best_p,n,temp,q,eye,d;
#ifdef MCH_AMIGA
node *best_obj = 1L;
#else
node *best_obj = (node *)1L;
#endif
float best_t,qnorm,ddotn,n1,n2;
int hitnext;
/* make local modifyable copies */
veccopy(eye2,eye);
veccopy(d2,d);
veczero(val);
CV(1.0,1.0,1.0,transparency);
all_intersects(eye,d,0);
hitnext = 0;
while ( best_obj &&
(transparency[0] > 0.01 ||
transparency[1] > 0.01 ||
transparency[2] > 0.01 ) )
{
best_obj = get_next_intersection(hitnext,best_p,&best_t);
if (best_obj)
{
getval(nextval,best_obj,best_p,d,atten,amblits);
vecmul(transparency,nextval,nextval);
vecsum(val,nextval,val);
vecmul(best_obj->attr.tra,transparency,transparency);
if (transparency[0] > 0.01 || /* Can some light get through? */
transparency[1] > 0.01 ||
transparency[2] > 0.01)
if ((best_obj->attr.idx != idxref) || /* Is it refractive? */
(best_obj->kind == SPHERE))
{ /* Is it a volume object? */
/* apply refraction by changing ray direction and origin */
findnormal(best_obj,best_p,n);
ddotn = DOT(d,n);
if (ddotn < 0.0)
{
n2 = best_obj->attr.idx;
n1 = idxref;
}
else
{
n1 = best_obj->attr.idx;
n2 = idxref;
n[0] = -n[0]; /* Negate the normal */
n[1] = -n[1];
n[2] = -n[2];
ddotn = -ddotn;
}
vecscale(ddotn,n,temp);
vecsub(d,temp,temp);
vecscale(n1 / n2,temp,q);
qnorm = NORM(q); /* magnitude */
if (qnorm >= 1.0)
best_obj = NULL; /* past critical angle,no more light */
else
{
vecscale(sqrt(1.0-(qnorm*qnorm)),n,temp);
vecsub(q,temp,d);
veccopy(best_p,eye);
hitnext = -1; /* new direction vector,so re-depth-sort intersections */
all_intersects(eye,d,0); /* Compute intersections with new ray */
}
}
hitnext++;
}
}
vecmul(backgroundval,transparency,nextval);
vecsum(val,nextval,val);
}